#!/bin/bash

daemon_name=nfs-server

NFSD_COUNT=
NFSD_OPTS=
NEED_SVCGSSD=
SVCGSSD_OPTS=
MOUNTD_OPTS=
PROCNFSD_MOUNTPOINT=
PROCNFSD_MOUNTOPTS=

# rpc.nfsd daemon & binary location
NFSD_PROCESS_NAME=nfsd
NFSD_DAEMON_NAME=rpc.nfsd
NFSD="/usr/sbin/rpc.nfsd"

# rpc.svcgssd daemon & binary location
SVCGSSD_DAEMON_NAME=rpc.svcgssd
SVCGSSD="/usr/sbin/rpc.svcgssd"

# rpc.idmapd daemon & binary location
IDMAPD_DAEMON_NAME=rpc.idmapd
IDMAPD="/usr/sbin/rpc.idmapd"

# rpc.mountd daemon & binary location
MOUNTD_DAEMON_NAME=rpc.mountd
MOUNTD="/usr/sbin/rpc.mountd"

# exortfs binary location
EXPORTFS="/usr/sbin/exportfs"

. /etc/rc.conf
. /etc/rc.d/functions
. /etc/conf.d/$daemon_name.conf

# Default number of nfsd servers
[ -z "$NFSD_COUNT" ] && NFSD_COUNT=8

# Default mountpoint and options for nfsd filesystem
[ -z "$PROCNFSD_MOUNTPOINT" ] && PROCNFSD_MOUNTPOINT="/proc/fs/nfsd"
[ -z "$PROCNFSD_MOUNTOPTS" ] && PROCNFSD_MOUNTOPTS="rw,nodev,noexec,nosuid"

case "$NEED_SVCGSSD" in
  yes|no)
    ;;
  *)
    NEED_SVCGSSD=no
    ;;
esac

do_modprobe() {
    if [ -x /sbin/modprobe -a -f /proc/modules ]; then
      modprobe -q "$1" || true
    fi
}

do_mount() {
    if ! grep -E "$1\$" /proc/filesystems &> /dev/null ; then
      return 1
    fi
    
    if grep -vw "$1" /proc/mounts &> /dev/null ; then
      if ! mountpoint -q "$2" ; then
	mount -t "$1" "$1" "$2" -o "$3"
	return
      fi
    fi
    return 0
}

do_umount() {
    if mountpoint -q "$1" ; then
      umount "$1"
    fi
    return 0
}

get_pid() {
	pidof -o %PPID "$1"
}

case "$1" in
  start)
    ck_daemon nfs-common && { echo -n "Start nfs-common first." >&2; stat_die; }
    rc=0
    stat_busy "Mounting nfsd filesystem"
    do_modprobe nfsd
    do_mount nfsd "$PROCNFSD_MOUNTPOINT" "$PROCNFSD_MOUNTOPTS"
    rc=$(($rc+$?))
    if [ $rc -gt 0 ]; then
      stat_fail
      exit $rc
    else
      stat_done
    fi

    stat_busy "Exporting all directories"
    $EXPORTFS -r
    rc=$(($rc+$?))
    if [ $rc -gt 0 ]; then
      stat_fail
      exit $rc
    else
      stat_done
    fi

    stat_busy "Starting $NFSD_DAEMON_NAME daemon"
    PID=$(get_pid $NFSD_PROCESS_NAME)
    if [ -z "$PID" ]; then
      [ -f /var/run/$NFSD_DAEMON_NAME.pid ] && rm -f /var/run/$NFSD_DAEMON_NAME.pid
      # RUN
      $NFSD $NFSD_OPTS $NFSD_COUNT
      #
      rc=$(($rc+$?))
      if [ $rc -gt 0 ]; then
	stat_fail
	exit $rc
      else
	echo $(get_pid $NFSD_PROCESS_NAME) > /var/run/$NFSD_DAEMON_NAME.pid
	stat_done
      fi
    else
      stat_fail
      exit 1
    fi

    if [ "$NEED_SVCGSSD" = yes ]; then
      do_modprobe rpcsec_gss_krb5
      stat_busy "Starting $SVCGSSD_DAEMON_NAME daemon"
      PID=$(get_pid $SVCGSSD)
      if [ -z "$PID" ]; then
	[ -f /var/run/$SVCGSSD_DAEMON_NAME.pid ] && rm -f /var/run/$SVCGSSD_DAEMON_NAME.pid
	# RUN
	$SVCGSSD $SVCGSSD_OPTS
	#
	rc=$(($rc+$?))
	if [ $rc -gt 0 ]; then
	  stat_fail
	  exit $rc
	else
	  echo $(get_pid $SVCGSSD) > /var/run/$SVCGSSD_DAEMON_NAME.pid
	  stat_done
	fi
      else
	stat_fail
	exit 1
      fi
    fi

    PID=$(get_pid $IDMAPD)
    [ ! -z "$PID" ] && kill -SIGHUP $IDMAPD_DAEMON_NAME &> /dev/null

    stat_busy "Starting $MOUNTD_DAEMON_NAME daemon"
    PID=$(get_pid $MOUNTD)
    if [ -z "$PID" ]; then
      [ -f /var/run/$MOUNTD_DAEMON_NAME.pid ] && rm -f /var/run/$MOUNTD_DAEMON_NAME.pid
      # RUN
      $MOUNTD $MOUNTD_OPTS
      #
      rc=$(($rc+$?))
      if [ $rc -gt 0 ]; then
	stat_fail
	exit $rc
      else
	echo $(get_pid $MOUNTD) > /var/run/$MOUNTD_DAEMON_NAME.pid
	stat_done
      fi
    else
      stat_fail
      exit 1
    fi

    add_daemon $daemon_name
    ;;

  stop)
    rc=0
    stat_busy "Stopping $MOUNTD_DAEMON_NAME daemon"
    PID=$(get_pid $MOUNTD)
    # KILL
    [ ! -z "$PID" ] && kill $PID &> /dev/null
    #
    rc=$(($rc+$?))
    if [ $rc -gt 0 ]; then
      stat_fail
      exit $rc
    else
      rm -f /var/run/$MOUNTD_DAEMON_NAME.pid &> /dev/null
      stat_done
    fi

    if [ "$NEED_SVCGSSD" = yes ]; then
      stat_busy "Stopping $SVCGSSD_DAEMON_NAME daemon"
      PID=$(get_pid $SVCGSSD)
      # KILL
      [ ! -z "$PID" ] && kill $PID &> /dev/null
      #
      rc=$(($rc+$?))
      if [ $rc -gt 0 ]; then
	stat_fail
	exit $rc
      else
	rm -f /var/run/$SVCGSSD_DAEMON_NAME.pid &> /dev/null
	stat_done
      fi
    fi

    stat_busy "Stopping $NFSD_DAEMON_NAME daemon"
    PID=$(get_pid $NFSD_PROCESS_NAME)
    # KILL (SIGINT)
    [ ! -z "$PID" ] && kill -2 $PID &> /dev/null
    #
    rc=$(($rc+$?))
    if [ $rc -gt 0 ]; then
      stat_fail
      exit $rc
    else
      sleep 1
      PID=$(get_pid $NFSD_PROCESS_NAME)
      # KILL (KILL) - just to be sure
      [ ! -z "$PID" ] && kill -9 $PID &> /dev/null
      #
      rm -f /var/run/$NFSD_DAEMON_NAME.pid &> /dev/null
      stat_done
    fi

    stat_busy "Unexporting all directories"
    $EXPORTFS -au
    rc=$(($rc+$?))
    if [ $rc -gt 0 ]; then
      stat_fail
      exit $rc
    else
      stat_done
    fi

    # flush everything out of the kernels export table
    if mountpoint -q "$PROCNFSD_MOUNTPOINT" ; then
      $EXPORTFS -f
    fi
    do_umount "$PROCNFSD_MOUNTPOINT" 2>/dev/null || true
    rm_daemon $daemon_name
    ;;

  status)
    stat_busy "Checking $daemon_name status";
    ck_status $daemon_name

    stat_busy "Daemon $NFSD_DAEMON_NAME running"
    PID=$(get_pid $NFSD_PROCESS_NAME)
    if [ -z "$PID" ]; then
      stat_fail
    else
      stat_done
    fi

    stat_busy "Daemon $MOUNTD_DAEMON_NAME running"
    PID=$(get_pid $MOUNTD)
    if [ -z "$PID" ]; then
      stat_fail
    else
      stat_done
    fi

    if [ "$NEED_SVCGSSD" = yes ]; then
      stat_busy "Daemon $SVCGSSD_DAEMON_NAME running"
      PID=$(get_pid $SVCGSSD)
      if [ -z "$PID" ]; then
	stat_fail
      else
	stat_done
      fi
    fi
    echo
    ;;

  reload)
    rc=0
    stat_busy "Re-exporting all directories"
    $EXPORTFS -r
    rc=$(($rc+$?))
    if [ $rc -gt 0 ]; then
      stat_fail
      exit $rc
    else
      stat_done
    fi
    ;;

  restart)
    $0 stop
    sleep 3
    $0 start
    ;;
  *)
    echo "usage: $0 {start|stop|status|reload|restart}"  
esac
exit 0
